package com.smarthome.web.property.auth;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.smarthome.common.tools.BossCachedKeysUtil;
import com.smarthome.common.tools.SHACipher;
import com.smarthome.common.tools.cache.JedisUtils;
import com.smarthome.core.housemanager.ResidenceManagerService;
import com.smarthome.core.user.PropertyEmployeeService;
import com.smarthome.core.user.PropertyUserService;
import com.smarthome.core.user.UserResourceService;
import com.smarthome.domain.bean.ShPropertyEmployee;
import com.smarthome.domain.bean.ShResidence;
import com.smarthome.domain.bean.ShUser;
import com.smarthome.domain.bean.ShUserResource;
import com.smarthome.domain.enums.ShUserSuperFlagEnum;
import com.smarthome.domain.vo.boss.MenuBean;

@Service("shiroRealm")
public class ShiroRealm extends AuthorizingRealm {

    private static final Logger logger = LoggerFactory.getLogger(ShiroRealm.class);
    @Resource
    private UserResourceService userResourceService;
    @Resource
    private PropertyUserService propertyUserService;
    @Resource
    private PropertyEmployeeService propertyEmployeeService;
    @Resource
    private ResidenceManagerService residenceManagerService;

    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        ShiroUser shiroUser = (ShiroUser) principals.fromRealm(getName()).iterator().next();
        Long userId = null != shiroUser ? shiroUser.getUserId() : null;
        if (userId != null) {
            String sessionId = "";
            try {
                sessionId = SHACipher.encrypt(shiroUser.getLoginName());
            } catch (Exception e) {
                e.printStackTrace();
            }
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
            List<ShUserResource> shUserResources = new ArrayList<ShUserResource>();
            List<ShResidence> residences = new ArrayList<ShResidence>();
            Long currentResidenceId = JedisUtils.getLong(BossCachedKeysUtil.getKey(BossCachedKeysUtil.MODULE_USER_RESIDENCE_PREFIX, sessionId));
            ShResidence currentResidence = new ShResidence();
            // if (shiroUser.isSuperAdmin()) {// 超级管理员默认拥有所有操作权限
            // ShResidence residence = residenceManagerService.queryResidenceById(Constants.PLATFORM_MANAGE_RESIDENCE_ID);
            // currentResidence = residence;
            // residences.add(residence);
            // if (null == currentResidenceId || currentResidenceId.equals(0L)) {
            // currentResidenceId = Constants.PLATFORM_MANAGE_RESIDENCE_ID;// 平台管理域
            // }
            // shUserResources = userResourceService.queryAllOpenedUserResources();
            // } else {// 非超级管理员
            residences = residenceManagerService.queryResidencesByUserId(userId);
            if (residences != null && (null == currentResidenceId || currentResidenceId.equals(0L))) {
                currentResidence = residences.get(0);
                currentResidenceId = currentResidence.getId();
                for (ShResidence residence : residences) {
                    if (currentResidenceId > residence.getId())
                        currentResidenceId = residence.getId();
                }
            } else {
                // ** add by dhc 2015/10/11
                currentResidence = residenceManagerService.queryResidenceById(currentResidenceId);
            }
            shUserResources = userResourceService.queryUserResourcesByUserAndRole(userId, currentResidenceId);
            // }
            JedisUtils.set(BossCachedKeysUtil.getKey(BossCachedKeysUtil.MODULE_USER_RESIDENCE_PREFIX, sessionId), currentResidenceId);
            ShUser shUser = propertyUserService.queryPropertyUserById(userId);
            shUser.setResidences(residences);
            shUser.setResources(shUserResources);
            shUser.setCurrentResidence(currentResidence);
            JedisUtils.set(BossCachedKeysUtil.getKey(BossCachedKeysUtil.MODULE_USER_PREFIX, sessionId), shUser);
            List<MenuBean> menuBeans = generateMenuTree(shUserResources, 0L);
            JedisUtils.set(BossCachedKeysUtil.getKey(BossCachedKeysUtil.MODULE_USER_RESOURCE, sessionId), JSONObject.toJSON(menuBeans).toString());
            if (shUserResources != null && shUserResources.size() != 0) {
                for (ShUserResource shUserResource : shUserResources) {
                    info.addStringPermission(shUserResource.getCode());
                }
                return info;
            }
        }
        return null;
    }

    private List<MenuBean> generateMenuTree(List<ShUserResource> shUserResources, Long parentId) {
        List<MenuBean> menuBeans = new ArrayList<MenuBean>();
        for (ShUserResource shUserResource : shUserResources) {
            if (parentId == shUserResource.getParentId()) {
                MenuBean menuBean = new MenuBean();
                menuBean.setId(shUserResource.getId());
                menuBean.setName(shUserResource.getName());
                menuBean.setCode(shUserResource.getCode());
                menuBean.setIconPath(shUserResource.getIconPath());
                menuBean.setAddress(shUserResource.getAddress());
                menuBean.setSubMenus(generateMenuTree(shUserResources, shUserResource.getId()));
                menuBeans.add(menuBean);
            }
        }
        return menuBeans;
    }

    // 获取认证信息
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
        UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
        // 通过表单接收的用户名
        String loginName = token.getUsername();
        if (loginName != null && !"".equals(loginName)) {
            ShUser shUser = propertyUserService.queryPropertyUserByLoginName(loginName);
            if (shUser != null) {
                ShPropertyEmployee shPropertyEmployee = propertyEmployeeService.queryPropertyEmployeeById(shUser.getEmployeeId());
                String employeeName = null == shPropertyEmployee ? "" : shPropertyEmployee.getName();
                ShiroUser shiroUser = new ShiroUser(shUser.getId(), employeeName, shUser.getLoginName(), shUser.getSuperFlag() == ShUserSuperFlagEnum.SUPER.getFlag());
                return new SimpleAuthenticationInfo(shiroUser, shUser.getLoginPwd(), getName());
            }
        }
        return null;
    }

    /**
     * 更新用户授权信息缓存.
     */

    public void clearCachedAuthorizationInfo(Object principal) {
        SimplePrincipalCollection principals = new SimplePrincipalCollection(principal, getName());
        clearCachedAuthorizationInfo(principals);
    }

    /**
     * 清除所有用户授权信息缓存.
     */

    public void clearAllCachedAuthorizationInfo() {
        Cache<Object, AuthorizationInfo> cache = getAuthorizationCache();
        if (cache != null) {
            for (Object key : cache.keys()) {
                cache.remove(key);
            }
        }
    }
}
